package cn.turboinfo.fuyang.api.provider.common.component.product.interceptor

import cn.turboinfo.fuyang.api.entity.common.enumeration.product.ProductStatus
import cn.turboinfo.fuyang.api.entity.common.event.WrapperApplicationEvent
import cn.turboinfo.fuyang.api.entity.common.event.product.ProductStatusChangedEvent
import cn.turboinfo.fuyang.api.provider.common.framework.jpa.interceptor.FlushDirtyInterceptor
import cn.turboinfo.fuyang.api.provider.common.framework.jpa.interceptor.SaveInterceptor
import cn.turboinfo.fuyang.api.provider.common.repository.database.product.ProductPO
import org.hibernate.type.Type
import org.springframework.context.ApplicationContext
import org.springframework.stereotype.Component
import org.springframework.transaction.support.TransactionSynchronization
import org.springframework.transaction.support.TransactionSynchronizationManager
import java.io.Serializable

/**
 * 商品状态处理拦截器
 */
@Component
class ProductStatusInterceptor(
    private val applicationContext: ApplicationContext,
) : SaveInterceptor, FlushDirtyInterceptor {

    override fun onSave(
        entity: Any,
        id: Serializable?,
        state: Array<Any>,
        propertyNames: Array<out String>,
        types: Array<out Type>
    ): Boolean {
        (entity as ProductPO)
            .apply {
                TransactionSynchronizationManager.registerSynchronization(object : TransactionSynchronization {
                    override fun afterCommit() {
                        applicationContext.publishEvent(
                            WrapperApplicationEvent(
                                ProductStatusChangedEvent.builder()
                                    .productId(entity.id)
                                    .status(entity.status)
                                    .build()
                            )
                        )
                    }
                })
            }

        return false
    }

    override fun onFlushDirty(
        entity: Any,
        id: Serializable,
        currentState: Array<Any>,
        previousState: Array<out Any>,
        propertyNames: Array<out String>,
        types: Array<out Type>
    ): Boolean {
        val index = propertyNames.indexOf("status")

        if (previousState[index] != currentState[index]) {
            (entity as ProductPO)
                .apply {
                    TransactionSynchronizationManager.registerSynchronization(object : TransactionSynchronization {
                        override fun afterCommit() {
                            applicationContext.publishEvent(
                                WrapperApplicationEvent(
                                    ProductStatusChangedEvent.builder()
                                        .productId(entity.id)
                                        .fromStatus(previousState[index] as ProductStatus)
                                        .status(currentState[index] as ProductStatus)
                                        .build()
                                )
                            )
                        }
                    })
                }
        }

        return false
    }

    override fun isSupported(
        entity: Any,
        id: Serializable,
        currentState: Array<out Any>,
        previousState: Array<out Any>,
        propertyNames: Array<out String>,
        types: Array<out Type>
    ): Boolean {
        return entity is ProductPO
    }

    override fun isSupported(
        entity: Any,
        id: Serializable?,
        state: Array<out Any>,
        propertyNames: Array<out String>,
        types: Array<out Type>
    ): Boolean {
        return entity is ProductPO
    }
}
